package com.dbapp.garden.controller.sys;

import com.dbapp.garden.common.DataTableUtils;
import com.dbapp.garden.common.RenderJSON;
import com.dbapp.garden.common.com.dbapp.garden.common.exception.BusinessException;
import com.dbapp.garden.config.security.PermissionUser;
import com.dbapp.garden.config.security.PermissionUtils;
import com.dbapp.garden.entity.GardenInfo;
import com.dbapp.garden.entity.SysResource;
import com.dbapp.garden.entity.SysRole;
import com.dbapp.garden.service.GardenInfoService;
import com.dbapp.garden.service.SysResourceService;
import com.dbapp.garden.service.SysRoleService;
import com.dbapp.garden.vm.SysRoleVm;
import com.dbapp.garden.vo.SysRoleVo;
import com.dbapp.garden.vo.Tree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 角色管理的控制器类
 *
 * @author gangzi
 */
@Controller
public class SysRoleController {

    public static final String ADMIN = "ADMIN";

    private static final Logger log = LoggerFactory.getLogger(SysRoleController.class);

    @Autowired
    private SysRoleService roleService;

    @Autowired
    private SysResourceService sysResourceService;

    @Autowired
    private GardenInfoService gardenInfoService;

    @GetMapping("/role")
    @PreAuthorize("hasAuthority('PERMISSION_ROLE_LIST')")
    public String toRoleListPage(Model model) {

        Map<String, Object> map = new HashMap<>(16);
        List<GardenInfo> gardenInfos = gardenInfoService.getGardenList(map);
        model.addAttribute("gardens", gardenInfos);
        return "role/rolelist";
    }

    @PostMapping("/rolelist")
    @ResponseBody
    @PreAuthorize("hasAuthority('PERMISSION_ROLE_LIST')")
    public Map<String, ?> roleList(String param, Integer gardenId, @SessionAttribute("user") PermissionUser user) {

        Map<String, Object> paramMap = DataTableUtils.parseParam(param);
        if (paramMap == null) {
            return RenderJSON.makeMap(-1, "参数不合法！", null, "");
        }

        String sEcho = (String) paramMap.get("sEcho");
        String sSearch = (String) paramMap.get("sSearch");
        int iDisplayStart = (int) paramMap.get("iDisplayStart");
        int iDisplayLength = (int) paramMap.get("iDisplayLength");

        paramMap.clear();
        paramMap.put("sSearch", sSearch);
        paramMap.put("start", iDisplayStart);
        paramMap.put("limit", iDisplayLength);
        boolean isGod = PermissionUtils.isGod(user);
        //如果是GOD权限，则可以查看所有角色，否则只能查看属于自己园所的角色
        if (!isGod) {
            paramMap.put("gardenId", user.getGardenId());
        } else {
            //GOD权限可以进行筛选
            if (gardenId != null && gardenId > 0) {
                paramMap.put("gardenId", gardenId);
            }
        }


        List<SysRole> roleList = roleService.getRoleList(paramMap);
        List<SysRoleVo> roleVos = roleList.stream().filter(role -> role.getGardenId() > 0).map(r -> {
            SysRoleVo roleVo = new SysRoleVo();
            roleVo.setId(r.getId());
            roleVo.setRoleName(r.getRoleName());
            roleVo.setCreateTime(r.getCreateTime());
            roleVo.setRoleCode(r.getRoleCode());
            roleVo.setRoleDesc(r.getRoleDesc());
            GardenInfo gardenInfo = gardenInfoService.findById(r.getGardenId());
            roleVo.setGardenName(gardenInfo.getGardenName());
            return roleVo;
        }).collect(Collectors.toList());
        Integer count = roleService.getRoleCount(paramMap);

        return RenderJSON.makePagenateMap(1, "获取成功", sEcho, count, count, roleVos, "");
    }

    @GetMapping("/roleview/{id}")
    @PreAuthorize("hasAuthority('PERMISSION_ROLE_VIEW')")
    public String toRoleViewPage(@PathVariable("id") Integer id, Model model) {
        SysRole role = roleService.findRoleById(id);
        List<SysResource> resourceList = sysResourceService.findByRoleId(id);
        List<Tree> treeData = parseAllTreeNode(resourceList, null);
        model.addAttribute("role", role);
        model.addAttribute("treeData", treeData);
        return "role/roleview";
    }

    @GetMapping("/role/{id}")
    @PreAuthorize("hasAuthority('PERMISSION_ROLE_EDIT')")
    public String toRoleEditPage(@PathVariable("id") Integer id, Model model, @SessionAttribute("user") PermissionUser user) {
        Map<String, Object> map = new HashMap<>(16);
        List<GardenInfo> gardenInfos = gardenInfoService.getGardenList(map);

        SysRole role = roleService.findRoleById(id);

        //非GOD用户，不能分配"园所管理权限"
        if (!PermissionUtils.isGod(user)) {
            map.clear();
            map.put("isGodRes", 0);
        }
        List<SysResource> resourceList = sysResourceService.findAllResources(map);
        List<SysResource> roleResList = sysResourceService.findByRoleId(id);
        List<Integer> resIds = roleResList.stream().map(res -> res.getId()).collect(Collectors.toList());
        List<Tree> treeData = parseAllTreeNode(resourceList, resIds);
        model.addAttribute("role", role);
        model.addAttribute("treeData", treeData);
        model.addAttribute("gardens", gardenInfos);
        return "role/roleedit";
    }


    @PostMapping(value = "/role", produces = "application/json;charset=utf-8;", consumes = "application/json")
    @PreAuthorize("hasAuthority('PERMISSION_ROLE_ADD')")
    @ResponseBody
    public Map<String, ?> roleAddSave(HttpServletRequest request, @RequestBody @Valid SysRoleVm roleVm, @SessionAttribute("user") PermissionUser user) {
        SysRole role = new SysRole();

        String roleCode = roleVm.getRoleCode();

        role.setRoleName(roleVm.getRoleName());
        role.setRoleCode(roleVm.getRoleCode());
        role.setRoleDesc(roleVm.getRoleDesc());
        role.setCreateTime(new Date());
        role.setUpdateTime(new Date());
        if (PermissionUtils.isGod(user)) {
            role.setGardenId(roleVm.getGardenId());
        } else {
            role.setGardenId(user.getGardenId());
            //ADMIN这个角色码，为每个园所的管理员标识，不允许普通用户分配
            if (ADMIN.equals(roleCode)) {
                return RenderJSON.makeStandMap(2, "对不起，ADMIN为特殊角色码，请更换！", "error");
            } else {
                role.setRoleCode(roleCode);
            }
        }
        roleService.saveRole(role, roleVm.getResIds());
        return RenderJSON.makeStandMap(1, "恭喜您，添加成功", "");
    }

    @PutMapping(value = "/role/{id}", produces = "application/json;charset=utf-8;", consumes = "application/json")
    @PreAuthorize("hasAuthority('PERMISSION_ROLE_EDIT')")
    @ResponseBody
    public Map<String, ?> roleEditSave(HttpServletRequest request, @PathVariable("id") Integer id, @RequestBody @Valid SysRoleVm roleVm, @SessionAttribute("user") PermissionUser user) {
        SysRole role = roleService.findRoleById(id);
        if (role == null) {
            return RenderJSON.makeStandMap(1, "对不起，编辑失败", "error");
        }
//        String roleCode = roleVm.getRoleCode();

        if (PermissionUtils.isGod(user)) {
            role.setGardenId(roleVm.getGardenId());
//            role.setRoleCode(roleCode);
        } else {
            //如果当前登录用户不是超级管理员，并且不是本园所的用户，则提示权限错误，防止越权
            if (!role.getGardenId().equals(user.getGardenId())) {
                throw new BusinessException("对不起，您不具备修改权限");
            }
            //ADMIN这个角色码，为每个园所的管理员标识，不允许普通用户分配
//            if (ADMIN.equals(roleCode)) {
//                return RenderJSON.makeStandMap(2, "对不起，ADMIN为特殊角色码，请更换！", "error");
//            } else {
//                role.setRoleCode(roleCode);
//            }
        }
        role.setRoleName(roleVm.getRoleName());
        role.setRoleDesc(roleVm.getRoleDesc());
        role.setUpdateTime(new Date());
        Integer result = roleService.saveRole(role, roleVm.getResIds());
        if (result != null && result > 0) {
            return RenderJSON.makeStandMap(1, "恭喜您，编辑成功", "ok");
        } else {
            return RenderJSON.makeStandMap(1, "对不起，编辑失败", "error");
        }

    }

    @DeleteMapping(value = "/role/{roleId}", produces = "application/json;charset=utf-8;")
    @PreAuthorize("hasAuthority('PERMISSION_ROLE_DELETE')")
    @ResponseBody
    public Map<String, ?> roleDelete(@PathVariable("roleId") Integer roleId, @SessionAttribute("user") PermissionUser user) {

        SysRole role = roleService.findRoleById(roleId);
        if (role == null) {
            return RenderJSON.makeStandMap(1, "对不起，角色不存在，删除失败", "error");
        }
        if (!PermissionUtils.isGod(user)) {
            //如果当前登录用户不是超级管理员，并且不是本园所的用户，则提示权限错误，防止越权
            if (!role.getGardenId().equals(user.getGardenId())) {
                throw new BusinessException("对不起，您不具备删除权限");
            }
        }
        Integer result = roleService.deleteRole(roleId);
        if (result != null && result > 0) {
            return RenderJSON.makeStandMap(1, "恭喜您，删除成功", "ok");
        } else {
            return RenderJSON.makeStandMap(1, "对不起，删除失败", "error");
        }

    }

    @GetMapping("/rolenamecheck")
    @ResponseBody
    public boolean checkRoleNameExit(String roleName, @SessionAttribute("user") PermissionUser user) {
        Map<String, Object> map = new HashMap<>(16);
        //这里校验，同一个园所的角色名不能重复
        if (!PermissionUtils.isGod(user)) {
            map.put("gardenId", user.getGardenId());
            map.put("roleName", roleName);
            SysRole role = roleService.findRoleByName(map);
            return role == null ? true : false;
        } else {
            //超级管理员用户可以随便添加
            return true;
        }

    }

    /**
     * 解析权限树
     *
     * @param resourceList
     * @param roleResIds
     * @return
     */
    private List<Tree> parseAllTreeNode(List<SysResource> resourceList, List<Integer> roleResIds) {
        return resourceList.stream().map(res -> {
            Tree treeNode = new Tree();
            treeNode.setId(res.getId());
            treeNode.setName(res.getResName());
            treeNode.setpId(res.getResParentId());
            treeNode.setOpen(true);
            if (roleResIds != null && !roleResIds.isEmpty()) {
                if (roleResIds.contains(res.getId())) {
                    treeNode.setChecked(true);
                }
            }
            return treeNode;
        }).collect(Collectors.toList());
    }
}
